home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
MacHack 1996
/
MacHack 1996.toast
/
Hacks
/
Hacks ’87
/
Source ƒ.sit
/
Source ƒ
/
C ƒ
/
CITADEL BBS 'C' SRC
/
LOG.C
< prev
next >
Wrap
C/C++ Source or Header
|
1987-01-14
|
16KB
|
517 lines
/************************************************************************/
/* log.c */
/* */
/* userlog code for Citadel bulletin board system */
/************************************************************************/
/************************************************************************/
/* history */
/* */
/* 85Nov15 HAW MS-DOS library implemented. */
/* 85Aug31 HAW Fix <.ep> problem. */
/* 85Aug17 HAW Update to onLine(). */
/* 85Aug10 HAW Fix so system doesn't go out to disk on short pwds. */
/* 85Jul26 HAW Kill noteLog(), insert anti-hack code in newPW(). */
/* 85Jun13 HAW Tweak code for networking stuff. */
/* 85Mar13 HAW Moved zapLogFile() and logInit and logSort into confg.c.*/
/* 85Jan19 HAW Fix terminate() so room prompt isn't tossed at modem. */
/* 85Jan19 HAW New Users are now directed to type ".help POLICY". */
/* 85Jan19 HAW Move findPerson() into file. */
/* 84Dec15 HAW Fix bug that allowed discovery of private rooms. */
/* 84Aug30 HAW Now we roll into the 16-bit world. */
/* 84Jun23 HAW&JLS Eliminating unused local variables using CRF. */
/* 84Jun19 JLS Fixed terminate so that Mail> doesn't screw up SYSOP. */
/* 84Apr04 HAW Started upgrade to BDS C 1.50a. */
/* 83Feb27 CrT Fixed login-in-Mail> bug. */
/* 83Feb26 CrT Limited # new messages for new users. */
/* 83Feb18 CrT Null pw problem fixed. */
/* 82Dec06 CrT 2.00 release. */
/* 82Nov03 CrT Began local history file & general V1.2 cleanup */
/************************************************************************/
#include "ctdl.h"
/************************************************************************/
/* contents */
/* */
/* findPerson() load log record for named person */
/* hash() hashes a string to an integer */
/* login() is menu-level routine to log caller in */
/* newPW() is menu-level routine to change a PW */
/* newUser() menu-level routine to log a new caller */
/* PWSlot() returns CTDLLOG.buf slot password is in */
/* slideLTab() support routine for sorting logTab */
/* storeLog() store data in log */
/* strCmpU() strcmp(), but ignoring case distinctions*/
/* terminate() menu-level routine to exit system */
/************************************************************************/
/************************************************************************/
/* External variable declarations in LOG.C */
/************************************************************************/
int thisSlot; /* logTab slot logBuf found via */
char loggedIn = FALSE; /* Global have-caller flag */
char prevChar; /* for EOLN/EOParagraph stuff */
char expert; /* true to suppress hints etc. */
char termUpper; /* uppercase only flag */
char termLF; /* LF-after-CR flag */
char aide; /* aide privileges flag */
char sendTime; /* send time msg created */
char oldToo; /* Send last old on new request?*/
unsigned char termWidth; /* width to format output to */
unsigned char termNulls; /* # nulls to send at EOLN */
static char pwChangeCount; /* Anti-hack variable */
/************************************************************************/
/* External variable definitions for LOG.C */
/************************************************************************/
extern struct logBuffer logBuf; /* Log buffer of a person */
extern struct lTable *logTab; /* RAM index of pippuls */
extern struct config cfg; /* Configuration variables */
extern struct rTable roomTab[]; /* RAM index of rooms */
extern struct aRoom roomBuf; /* Room buffer */
extern FILE *logfl; /* log file descriptor */
extern int thisLog; /* entry currently in logBuf */
extern char outFlag; /* Output skip flag */
extern char whichIO; /* Where IO's going... */
extern char haveCarrier; /* Do we still got carrier? */
extern char echo; /* Who gets what */
extern char onConsole; /* Where we get stuff from */
extern int thisRoom; /* The room we're in */
extern int lastRoom;
extern int exitValue;
/************************************************************************/
/* External function definitions for LOG.C */
/************************************************************************/
int fread();
char toUpper();
/************************************************************************/
/* findPerson() loads log record for named person. */
/* RETURNS: ERROR if not found, else log record # */
/************************************************************************/
int findPerson(name, lBuf)
char *name;
struct logBuffer *lBuf;
{
int h, i, foundIt, logNo;
h = hash(name);
for (foundIt = i = 0; i < cfg.MAXLOGTAB && !foundIt; i++) {
if (logTab[i].ltnmhash == h) {
getLog(lBuf, logNo = logTab[i].ltlogSlot);
if (strCmpU(name, lBuf->lbname) == SAMESTRING) {
foundIt = TRUE;
}
}
}
if (!foundIt) return ERROR;
else return logNo;
}
/************************************************************************/
/* hash() hashes a string to an integer */
/************************************************************************/
int hash(str)
char *str;
{
int h, i, shift;
for (h=shift=0; *str; shift=(shift+1)&7, str++) {
h ^= (i=toUpper(*str)) << shift;
}
return h;
}
/************************************************************************/
/* login() is the menu-level routine to log someone in */
/************************************************************************/
login(password)
char *password; /* TRUE if parameters follow */
{
char getYesNo();
int foundIt, ltentry;
foundIt = ((ltentry = PWSlot(password, /*load = */TRUE)) != ERROR);
pwChangeCount = 1;
if (foundIt && *password) {
/* update userlog entries: */
loggedIn = TRUE;
setUp(TRUE);
/* recite caller's name, etc: */
mPrintf(" %s\n", logBuf.lbname);
logMessage(L_IN, logBuf.lbname, FALSE);
showMessages(NEWoNLY, FALSE);
/* listRooms(!expert); */
listRooms(expert ? NORNEW : LINNEW);
if (!expert)
listRooms(NOROLD);
outFlag = OUTOK;
if (
(
logBuf.lbId[MAILSLOTS-1]
-
(logBuf.lbvisit[ logBuf.lbgen[MAILROOM] & CALLMASK ]+1)
< 0x8000
)
&&
logBuf.lbId[MAILSLOTS-1] - cfg.oldest < 0x8000
&&
thisRoom != MAILROOM
) {
mPrintf("\n * You have private mail in Mail> *\n ");
}
} else {
/* discourage password-guessing: */
if (strLen(password) > 1 && whichIO == MODEM)
pause(2000);
if (!cfg.unlogLoginOk && whichIO == MODEM) {
mPrintf(" No record -- leave message to 'sysop' in Mail>\n ");
} else if (getYesNo(" No record: Enter as new user")) newUser();
}
}
/************************************************************************/
/* newPW() is menu-level routine to change one's password */
/* since some Citadel nodes run in public locations, we avoid */
/* displaying passwords on the console. */
/************************************************************************/
newPW()
{
char oldPw[NAMESIZE];
char pw[NAMESIZE];
int goodPW;
/* save password so we can find current user again: */
if (!loggedIn) {
mPrintf("\n How?\n ");
return ;
}
strcpy(oldPw, logBuf.lbpw);
storeLog();
do {
echo = CALLER;
getNormStr(" new password", pw, NAMESIZE, NO_ECHO);
echo = BOTH;
/* check that PW isn't already claimed: */
goodPW = (PWSlot(pw,/* load = */TRUE) == ERROR && strLen(pw) >= 2);
if (pwChangeCount == 0) {
mPrintf("Hang on....\n");
pause(3000); /* Discourage hacking */
}
else pwChangeCount--;
if (!goodPW) mPrintf("\n Poor password\n ");
} while (!goodPW && (haveCarrier || whichIO==CONSOLE));
doCR();
PWSlot(oldPw, /*load = */TRUE); /* reload old log entry */
pw[NAMESIZE-1] = 0x00; /* insure against loss of carrier:*/
if (goodPW && strLen(pw) > 1) { /* accept new PW: */
strcpy(logBuf.lbpw, pw);
logTab[0].ltpwhash = hash(pw);
storeLog();
}
mPrintf("\n %s\n pw: ", logBuf.lbname);
echo = CALLER;
mPrintf("%s\n ", logBuf.lbpw);
echo = BOTH;
}
/************************************************************************/
/* newUser() prompts for name and password */
/************************************************************************/
newUser()
{
char getYesNo();
char fullnm[NAMESIZE];
char pw[NAMESIZE];
int good, g, h, i, ok, ourSlot;
ulong low;
configure(FALSE); /* make sure new users configure reasonably */
if (!expert) tutorial("password.blb");
do {
/* get name and check for uniqueness... */
do {
getNormStr(" Name", fullnm, NAMESIZE, ECHO);
h = hash(fullnm);
for (i = 0, good = TRUE; i < cfg.MAXLOGTAB && good; i++) {
if (h == logTab[i].ltnmhash) good = FALSE;
}
if (
h == 0 /* "HUH?" --HAW 84Aug31 */
||
h == hash("Citadel")
||
h == hash("Sysop")
) {
good = FALSE;
}
/* lie sometimes -- hash collision !=> name collision */
if (!good) mPrintf("We already have a %s\n", fullnm);
} while (!good && (haveCarrier || whichIO==CONSOLE));
/* get password and check for uniqueness... */
do {
echo = CALLER;
getNormStr(" password", pw, NAMESIZE, ECHO);
echo = BOTH ;
h = hash(pw);
for (i = 0, good = strLen(pw) > 1;
i < cfg.MAXLOGTAB && good;
i++) {
if (h == logTab[i].ltpwhash) good = FALSE;
}
if (h == 0) good = FALSE;
if (!good) {
mPrintf("\n Poor password\n ");
}
} while( !good && (haveCarrier || whichIO==CONSOLE));
mPrintf("\n nm: %s", fullnm);
mPrintf("\n pw: ");
echo = CALLER;
mPrintf("%s\n ", pw);
echo = BOTH;
} while (!getYesNo("OK") && (haveCarrier || whichIO==CONSOLE));
if (ok && (haveCarrier || whichIO == CONSOLE)) {
logMessage(L_IN, fullnm, '+');
/* kick least recent caller out of userlog and claim entry: */
ourSlot = logTab[cfg.MAXLOGTAB-1].ltlogSlot;
slideLTab(0, cfg.MAXLOGTAB-1);
logTab[0].ltlogSlot = ourSlot;
getLog(&logBuf, ourSlot);
/* copy info into record: */
strcpy(logBuf.lbname, fullnm);
strcpy(logBuf.lbpw, pw);
logBuf.lbflags.L_INUSE = TRUE;
logBuf.lbflags.lflag1 =
logBuf.lbflags.lflag2 =
logBuf.lbflags.lflag3 =
logBuf.lbflags.lflag4 =
logBuf.lbflags.lflag5 =
logBuf.lbflags.lflag6 =
logBuf.lbflags.lflag7 =
logBuf.lbflags.lflag8 =
logBuf.lbflags.lflag9 = FALSE;
logBuf.lbflags.NET_PRIVS = FALSE;
logBuf.credit = 0; /* No L-D credit */
low = cfg.newest-50;
if (cfg.oldest - low < 0x8000) low = cfg.oldest;
for (i=1; i<MAXVISIT; i++) logBuf.lbvisit[i]= low;
logBuf.lbvisit[ 0]= cfg.newest;
logBuf.lbvisit[ (MAXVISIT-1)]= cfg.oldest;
/* initialize rest of record: */
for (i = 0; i < MAXROOMS; i++) {
if (roomTab[i].rtflags.PUBLIC == 1) {
g = (roomTab[i].rtgen);
logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
} else {
/* set to one less */
g = (roomTab[i].rtgen + (MAXGEN-1)) % MAXGEN;
logBuf.lbgen[i] = (g << GENSHIFT) + (MAXVISIT-1);
}
}
for (i = 0; i < MAILSLOTS; i++) {
logBuf.lbslot[i] = 0l;
logBuf.lbId[ i] = cfg.oldest -1;
}
/* fill in logTab entries */
logTab[0].ltpwhash = hash(pw) ;
logTab[0].ltnmhash = hash(fullnm) ;
logTab[0].ltlogSlot = thisLog ;
logTab[0].ltnewest = logBuf.lbvisit[0];
/* special kludge for Mail> room, to signal no new mail: */
roomTab[MAILROOM].rtlastMessage = logBuf.lbId[MAILSLOTS-1];
loggedIn = TRUE;
storeLog();
/* listRooms(!expert); */
listRooms(expert ? NORNEW : LINNEW);
if (!expert)
listRooms(NOROLD);
mPrintf("\n \n Please type \".Help POLICY\"\n ");
}
}
/************************************************************************/
/* PWSlot() returns userlog.buf slot password is in, else ERROR */
/* NB: we also leave the record for the user in logBuf. */
/************************************************************************/
int PWSlot(pw, load)
char pw[NAMESIZE], load;
{
int h, i;
int foundIt, ourSlot;
struct logBuffer lBuf;
if (strLen(pw) < 2) /* Don't search for these pwds */
return ERROR;
h = hash(pw);
/* Check all passwords in memory: */
for(i = 0, foundIt = FALSE; !foundIt && i < cfg.MAXLOGTAB; i++) {
/* check for password match here */
/* If password matches, check full password */
/* with current newUser code, password hash collisions should */
/* not be possible... but this is upward compatable & cheap */
if (logTab[i].ltpwhash == h) {
ourSlot = logTab[i].ltlogSlot;
getLog(&lBuf, ourSlot);
if (strCmpU(pw, lBuf.lbpw) == SAMESTRING) {
/* found a complete match */
thisSlot = i ;
foundIt = TRUE;
}
}
}
if (foundIt) {
if (load == TRUE) {
movmem(&lBuf, &logBuf, sizeof logBuf);
thisLog = ourSlot;
}
return thisSlot;
}
else return ERROR ;
}
/************************************************************************/
/* slideLTab() slides bottom N lots in logTab down. For sorting. */
/************************************************************************/
slideLTab(slot, last)
int slot;
int last;
{
int i;
/* open slot up: (movmem isn't guaranteed on overlaps) */
for (i = last - 1; i >= slot; i--) {
movmem(&logTab[i], &logTab[i + 1], cfg.sizeLTentry);
}
}
/************************************************************************/
/* storeLog() stores the current log record. */
/************************************************************************/
storeLog()
{
logTab[0].ltnewest = cfg.newest;
logBuf.lbvisit[0] = cfg.newest;
logBuf.lbwidth = termWidth;
logBuf.lbnulls = termNulls;
logBuf.lbflags.EXPERT = (expert) ? TRUE : FALSE;
logBuf.lbflags.UCMASK = (termUpper) ? TRUE : FALSE;
logBuf.lbflags.LFMASK = (termLF) ? TRUE : FALSE;
logBuf.lbflags.AIDE = (aide) ? TRUE : FALSE;
logBuf.lbflags.TIME = (sendTime) ? TRUE : FALSE;
logBuf.lbflags.OLDTOO = (oldToo) ? TRUE : FALSE;
putLog(&logBuf, thisLog);
}
/************************************************************************/
/* strCmpU() is strcmp(), but ignoring case distinctions */
/************************************************************************/
int strCmpU(s, t)
char s[], t[];
{
int i;
i = 0;
while (toUpper(s[i]) == toUpper(t[i])) {
if (s[i++] == '\0') return 0;
}
return toUpper(s[i]) - toUpper(t[i]);
}
/************************************************************************/
/* terminate() is menu-level routine to exit system */
/************************************************************************/
terminate(discon)
char discon;
/* 1. parameter <discon> is TRUE or FALSE. */
/* 2. if <discon> is TRUE, breaks modem connection */
/* or switches whichIO from CONSOLE to MODEM, */
/* as appropriate. */
/* 3. modifies externs: struct logBuf, */
/* struct *logTab */
/* 4. returns no values */
/* modified dvm 9-82 */
{
int i;
char doStore;
int year, day, hours, minutes;
char *month;
doStore = onLine();
if (loggedIn)
mPrintf(" %s logged out\n ", logBuf.lbname);
if (discon) {
switch (whichIO) {
case MODEM:
interpret(cfg.pHangUp);
modIn(); /* And now detect carrier loss */
break;
case CONSOLE:
whichIO = MODEM;
printf("\n'MODEM' mode.\n ");
break;
}
getdate(&year, &month, &day, &hours, &minutes);
printf("%d%s%02d @ %d:%02d\n", year, month, day, hours, minutes);
}
if (loggedIn) {
logBuf.lbgen[thisRoom] = roomBuf.rbgen << GENSHIFT;
if (doStore) storeLog();
logMessage(L_OUT, "", (discon) ? 0 : '-');
loggedIn = FALSE;
setUp(TRUE);
}
for (i = 0; i < MAXROOMS; i++) /* Clear skip bits */
roomTab[i].rtflags.SKIP = 0;
lastRoom = -1;
}